package com.sn.author.monitor.handler;


import com.alibaba.fastjson.JSON;
import com.sn.author.common.context.SpringContext;
import com.sn.author.common.enums.TaskEnums;
import com.sn.author.common.enums.TaskTypeEnum;
import com.sn.author.common.sdk.AbstractResponse;
import com.sn.author.domain.taskEntity.TaskModel;
import com.sn.author.domain.taskEntity.TaskProcess;
import com.sn.author.redis.RedisKeyBuild;
import com.sn.author.redis.RedisUtil;
import com.sn.author.service.dao.*;
import com.sn.author.service.impl.TaskServiceImpl;
import com.sn.author.utils.SdkProcessService;
import lombok.extern.slf4j.Slf4j;

/**
 * @Author xiaom
 * @Date 2020/9/22 18:01
 * @Version 1.0.0
 * @Description <>
 **/
@Slf4j
public abstract class AbsHandler implements Handler{

    TaskModel taskModel;

    public AbsHandler(TaskModel taskModel) {
        this.taskModel = taskModel;
    }

    private void taskUpdate() {
        updateTaskProcessInfo();
    }

    /**
     * 推送成功消息到redis 等待前端获取展示
     */
    public void pushMessage(String message){
        getPushMessageService().pushMessage(PushMessageService.buildTaskPushMessage(message,taskModel.getTaskId(),taskModel.getTaskType()));
    }

    @Override
    public void execute() throws Exception {
        try {
            AbstractResponse response = requestApi();
            if(response == null || !response.getCode().equals("0")){
                throw new Exception("调用抖音 【" + TaskService.getTaskDesc(taskModel.getTaskType()) + "】 api返回结果异常 响应值:" + JSON.toJSONString(response));
            }
            log.info(getSuccessMessage());
            if(isPushMessage()){
                //推送进度消息
                pushMessage(getSuccessMessage());
            }
            //数据跟新
            responseAfter(response);
            updateTaskStatus(TaskEnums.FINISH.getCode());
        } catch (Exception e){
            log.info("执行任务出现异常 taskType:[{}] message:{}", TaskTypeEnum.match(taskModel.getTaskType()),e.getMessage());
            e.printStackTrace();
            pushMessage(getErrorMessage(e.getMessage()));
            responseErrAfter(e.getMessage());
            updateTaskStatus(TaskEnums.STOP.getCode());
        }finally {
            //任务更新
            taskUpdate();
        }
    }

    abstract AbstractResponse requestApi();


    private void updateTaskProcessInfo(){
        String cacheKey = RedisKeyBuild.buildTaskProcessKey(TaskServiceImpl.parserKey(taskModel.getTaskType()),taskModel.getTaskId());
        //获取任务基本信息
        String taskProcessStr = RedisUtil._REDIS_MODULE.get(cacheKey);
        if(taskProcessStr == null){
            log.error("【" + TaskService.getTaskDesc(taskModel.getTaskType()) + "】出现异常情况 不存在key为:" + cacheKey + " 的任务进度信息");
            return;
        }
        TaskProcess taskProcess = JSON.parseObject(taskProcessStr,TaskProcess.class);
        taskProcess.setOverCnt((taskProcess.getOverCnt() == null ? 0 : taskProcess.getOverCnt()) + 1);

        RedisUtil._REDIS_MODULE.set(cacheKey,taskProcess);
    }

    SdkProcessService getSdkService(){
        return SpringContext.getBean(SdkProcessService.class);
    }

    AccountService getAccountService(){
        return SpringContext.getBean(AccountService.class);
    }

    VideoService getVideoService(){
        return SpringContext.getBean(VideoService.class);
    }

    CollectionService getCollectionService(){
        return SpringContext.getBean(CollectionService.class);
    }

    TaskService getTaskService(){
        return SpringContext.getBean(TaskService.class);
    }

    private PushMessageService getPushMessageService(){
        return SpringContext.getBean(PushMessageService.class);
    }

    abstract String getSuccessMessage();

    abstract String getErrorMessage(String errmsg);

    boolean isPushMessage(){
        return true;
    }

    @Override
    public void responseAfter(AbstractResponse response) {

    }

    @Override
    public void responseErrAfter(String errMsg) {

    }

    public void updateTaskStatus(Integer status){
        getTaskService().updateTaskStatusByTaskId(taskModel.getTaskId(),status);
    }
}
